package cn.zdsoft.configuration.core.listener;

import cn.zdsoft.configuration.core.Constants;
import cn.zdsoft.configuration.core.api.CallbackAble;
import org.I0Itec.zkclient.IZkChildListener;
import org.I0Itec.zkclient.IZkDataListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Properties;

/**
 * 监听器
 * Created by wangdongdong on 2018/5/14.
 */
public class ZKListener implements IZkDataListener, IZkChildListener {

    private static final Logger logger = LoggerFactory.getLogger(ZKListener.class);

    private CallbackAble callbackAble;

    @Override
    public void handleChildChange(String path, List<String> list) throws Exception {
        logger.info("==========================>add key '{}'" + pathToKey(path));
    }

    @Override
    public void handleDataChange(String path, Object o) throws Exception {
        if (this.callbackAble == null) {
            logger.info("==========================>no callback, please restart system to reload key [{}:{}]", pathToKey(path), o.toString());
        }
        Object obj = this.callbackAble.getConfigContext().getAttribute(Constants.CONFIG_CONTEXT_PROPERTIES);
        if (obj == null) {
            throw new IllegalStateException(Constants.CONFIG_CONTEXT_PROPERTIES + "not exist");
        }
        Properties props = (Properties) obj;

        String key = pathToKey(path);
        String originValue = props.getProperty(pathToKey(path));
        if (originValue != null && o != null && !originValue.equals(o.toString().trim())) {
            this.callbackAble.onChange(key, originValue, o.toString().trim());
        }
    }

    @Override
    public void handleDataDeleted(String path) throws Exception {
        logger.info("==========================>the key '{}' has been delete", pathToKey(path));
    }

    /**
     * 节点路径转为key
     * @param path
     * @return
     *        /configuration/config/dev/app1/username -> username
     */
    private String pathToKey(String path) {
        return path.substring(path.lastIndexOf("/") + 1);
    }

    public void setCallbackAble(CallbackAble callbackAble) {
        this.callbackAble = callbackAble;
    }
}
